package com.beck.code.generator.generatorProcessor;

import com.beck.code.generator.JDBCConnectionFactory;
import com.beck.code.generator.configProperty.ContextConfig;
import com.beck.code.generator.configProperty.TableConfig;
import com.beck.code.generator.vo.DatabaseTableMetaDataVO;
import lombok.Data;

import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.LinkedList;
import java.util.List;

/**
 * @author CuiJianbo
 * @since 2025/7/1
 */
@Data
public class ContextGenerator {
    private ContextConfig contextConfig;
    private static DatabaseTableMetaDataVO databaseTableMetaDataVO;
    public static List<IntrospectedTable> tables;

    public static ContextGenerator getContextGenerator(ContextConfig config) {
        ContextGenerator contextGenerator = new ContextGenerator();
        contextGenerator.setContextConfig(config);
        return contextGenerator;
    }

    /**
     * 获取表字段数据
     */
    public void generateIntrospectedTables() {
        JDBCConnectionFactory jdbcConnectionFactory = new JDBCConnectionFactory(contextConfig.getJdbcConnectionConfig());
        List<IntrospectedTable> introspectedTables = new LinkedList<>();
        try {
            Connection connection = jdbcConnectionFactory.getConnection();
            DatabaseMetaData databaseMetaData = connection.getMetaData();

            for (TableConfig tc : contextConfig.getTableConfigList()) {
                IntrospectedTable introspectedTable = new IntrospectedTable();
                List<IntrospectedColumn> introspectedColumns = new LinkedList<>();
                ResultSet rs = databaseMetaData.getColumns(connection.getCatalog(), connection.getSchema(), tc.getTableName(), "%");
                while (rs.next()) {
                    IntrospectedColumn introspectedColumn = new IntrospectedColumn();
                    introspectedColumn.setJdbcTypeValue(rs.getString("TYPE_NAME"));
                    introspectedColumn.setColumnName(rs.getString("COLUMN_NAME"));
                    introspectedColumn.setRemarks(rs.getString("REMARKS"));
                    introspectedColumns.add(introspectedColumn);
                }
                introspectedTable.setIntrospectedColumns(introspectedColumns);
                introspectedTable.setTableName(tc.getTableName());
                introspectedTables.add(introspectedTable);
                this.closeResultSet(rs);
            }

            DatabaseTableMetaDataVO databaseMetaDataVO = new DatabaseTableMetaDataVO();
            databaseMetaDataVO.setCatalog(connection.getCatalog());
            databaseMetaDataVO.setSchema(connection.getSchema());
            databaseMetaDataVO.setDatabaseMetaData(databaseMetaData);
            databaseTableMetaDataVO = databaseMetaDataVO;
            tables = introspectedTables;
        } catch (Exception e) {
            throw new RuntimeException("Could not connect to database", e);
        }
    }

    private void closeResultSet(ResultSet rs) {
        if (rs != null) {
            try {
                rs.close();
            } catch (SQLException var3) {
            }
        }

    }

    public void generateCode() {
        for (TableConfig tableConfig : contextConfig.getTableConfigList()) {
            IntrospectedTable introspectedTable = tables.stream().filter(p -> p.getTableName().equals(tableConfig.getTableName())).findFirst().orElse(null);
            MapperXmlGenerator.getInstance(tableConfig, introspectedTable, contextConfig).generateCodeFile();
            DaoGenerator.getInstance(tableConfig, introspectedTable, contextConfig).generateCodeFile();
            ControllerGenerator.getInstance(tableConfig, introspectedTable, contextConfig).generateCodeFile();
            ServiceGenerator.getInstance(tableConfig, introspectedTable, contextConfig).generateCodeFile();
            VOGenerator.getInstance(tableConfig, introspectedTable, contextConfig).generateCodeFile();
        }
    }

    public static IntrospectedTable getTableMetaData(String tableName) {
        List<IntrospectedColumn> introspectedColumns = new LinkedList<>();
        IntrospectedTable introspectedTable = new IntrospectedTable();
        introspectedTable.setTableName(tableName);
        try {
            ResultSet rs = databaseTableMetaDataVO.getDatabaseMetaData().getColumns(databaseTableMetaDataVO.getCatalog(), databaseTableMetaDataVO.getSchema(), tableName, "%");
            while (rs.next()) {
                IntrospectedColumn introspectedColumn = new IntrospectedColumn();
                introspectedColumn.setJdbcTypeValue(rs.getString("TYPE_NAME"));
                introspectedColumn.setColumnName(rs.getString("COLUMN_NAME"));
                introspectedColumn.setRemarks(rs.getString("REMARKS"));
                introspectedColumns.add(introspectedColumn);
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
        introspectedTable.setIntrospectedColumns(introspectedColumns);
        return introspectedTable;
    }
}
